/**
 * Copyright 2002 Cordys R&D B.V. 
 * 
 * This file is part of the Cordys .NET Connector. 
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 //@Author	: Lejil 
//@Class	: NativeToCTS


#include "stdAfx.h"
#include "NativeToCTS.h"

/**
*	Parse the request from the native xml nom pointer
*	and get  information about  method parameters and constructor args
*
*		<Add xmlns="http://testmethod">
*			<param1>10</param1>
*			<param2>34</param2>  
*		</Add> 
*
*
**/
void  NativeToCTS::ParseRequest(int request, int typeNode)
{
	try
	{
		mtdParamDataNode		=	Node::GetFirstChildElement(request);
		methodArgument			=	ConvertArguments(mtdParamDataNode,typeNode); 
	}
	catch(Exception *ex)
	{
		throw ex;
	}
}


/**
*	Parse the method implementation from the native xml nom pointer
*	and get  information about  the assembly,class and method
*
*	<implementation type="DotnetCall">
*		<assembly>D:\jnetTestCases\bin\Debug\jnetTestCases.dll</assembly>
*		<class>jnetTestCases.arithmetic.Calculate</class>
*		<method dt="int" scope="out" ct="" static="true">Add</method>
*		<parameters>
*			<param1 dt="int"/>
*			<param2 dt="int"/>
*		</parameters>
*	</implementation>
*/
void  NativeToCTS::ParseImplementation(int implementation)
{
	try
	{
		//int assemblyNode	=	Find::FirstMatch(implementation,"?<assembly>");
		//classNode			=	Find::FirstMatch(implementation,"?<class>");
		//methodNode			=	Find::FirstMatch(implementation,"?<method>");

		//No need to add namespace support here
		int assemblyNode	=	Node::GetElement(implementation,"assembly");
		classNode			=	Node::GetElement(implementation,"class");
		methodNode			=	Node::GetElement(implementation,"method");
		
		assemblyName		=	Node::GetData(assemblyNode);
		methodName			=	Node::GetData(methodNode);
		
		operation			=   Node::GetAttribute(methodNode,"static","true")->Equals("true")? 0x01:0x02;
		operation			=   Node::GetAttribute(methodNode,"metadata","false")->Equals("true")? 0x03:operation;
	}
	catch(Exception *ex)
	{
		throw ex;
	}
}


//
//	Creates an Object Array from method arguements 
//		
//	   Required for creating instance and invoking methods.
//	   __box is used to convert value type to reference Type	
//
Object __gc *  NativeToCTS::ConvertArguments(int argumentNode,int dataTypeNode)[]
{
	
	int argumentCount	=	Node::GetNumChildElements(dataTypeNode);
	Object __gc * arguments[] = NULL;
	
	try
	{
		if (argumentCount > 0)
		{

				int child				=	argumentNode;
				int typeNode			=	Node::GetFirstElement(dataTypeNode);
				arguments				=   new  Object*[argumentCount];

				String  * dataType		=	NULL;
				String  * dataValue		=   NULL;
		
				for (int count  =0; count < argumentCount; count++)
				{
					
					dataType				=		Node::GetAttribute(typeNode,"dt");
					dataValue				=		Node::GetData(child,"NULL");

					if ( dataValue->Equals("NULL") )
					{
						dataValue	=	Node::GetAttribute(typeNode,"defaultValue","");
					}
					
					
					if (dataType->Equals("boolean"))
					{	
						arguments[count]	 =__box(Boolean::Parse(dataValue));
					}
					else if (dataType->Equals("i1"))
					{
						arguments[count]	 =__box(Byte::Parse(dataValue));
					}
					else if (dataType->Equals("si1"))
					{
						arguments[count]	 =__box(SByte::Parse(dataValue));
					}
					else if (dataType->Equals("char"))
					{
						arguments[count]	 =__box(Char::Parse(dataValue));
					}
					else if (dataType->Equals("r8"))
					{
						arguments[count]	 =__box(Double::Parse(dataValue));
					}
					else if (dataType->Equals("r4"))
					{
						arguments[count]	 =__box(Single::Parse(dataValue));
					}
					else if (dataType->Equals("i4") )
					{
						arguments[count]	 =__box(Int32::Parse(dataValue));
					}
					else if (dataType->Equals("i8"))
					{
						arguments[count]	 =__box(Int64::Parse(dataValue));
					}
					else if (dataType->Equals("i2"))
					{
						arguments[count]	=__box(Int16::Parse(dataValue));
					}
					else if (dataType->Equals("string"))
					{
						arguments[count]   = dataValue;
					}
					else if	 (dataType->Equals("dateTime"))
					{
						arguments[count]  = __box(DateTime::Parse(dataValue));
					}
					else  if (dataType->Equals("xml"))
					{
						arguments[count]		=  CovertToXmlDocument(child);
					}
					else  
					{
						throw new Exception("Type Not Supported");
					}
					child		= Node::GetNextElement(child);
					typeNode	= Node::GetNextElement(typeNode);
					
					dataValue		= NULL;
					dataType		= NULL;
				} 
				
		 }
					
	}
	catch(Exception *ex)
	{
		throw ex;
	}
	return arguments;
}


//
//  Create an XmlDocument from Sting in xml format, if 
//		the method arguments are xml
//
XmlDocument * NativeToCTS::CovertToXmlDocument(int xmlArgumentNode)
{
	String  * argString = Node::GetData(xmlArgumentNode,"NULL");
	XmlDocument *xmlArgument= new XmlDocument();
	xmlArgument->LoadXml(argString);
	return xmlArgument;
}

